package com.hp.tiger.concurrent.classloader.chapter3;

import com.google.common.base.Strings;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

/**
 * @author XavierDong
 **/
public class MyClassLoader extends ClassLoader {

    private static final String DEFAULT_DIR = "/Users/xavierdong/Documents/classloader1";

    private String dir = DEFAULT_DIR;

    private String classLoaderName;

    public MyClassLoader(String classLoaderName) {
        this.classLoaderName = classLoaderName;
    }


    public MyClassLoader(String classLoaderName, ClassLoader parent) {
        super(parent);
        this.classLoaderName = classLoaderName;


    }

    public MyClassLoader() {
    }

    public String getDir() {
        return dir;
    }

    public void setDir(String dir) {
        this.dir = dir;
    }

    public String getClassLoaderName() {
        return classLoaderName;
    }


    /**
     * xxxx.xxxx.xxxx.AAA------> xxxx/xxxx/xxxx/AAA.class
     *
     * @param name xxxx.xxxx.xxxx.AAA
     * @return
     * @throws ClassNotFoundException
     */
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {

        if (Strings.isNullOrEmpty(name))
            throw new ClassNotFoundException("load the class " + name + " failed");

        String classpath = name.replace('.', '/');
        File classFile = new File(dir, classpath + ".class");
        if (!classFile.exists())
            throw new ClassNotFoundException("The class " + name + " not found under " + dir);
        byte[] classBytes = loadBytesClass(classFile);

        if (classBytes == null || classBytes.length == 0)
            throw new ClassNotFoundException("load the class " + name + " failed");

        return this.defineClass(name, classBytes, 0, classBytes.length);
    }

    private byte[] loadBytesClass(File classFile) {

//        try {
//            return Files.asByteSource(classFile).read();
//        } catch (IOException e) {
//            e.printStackTrace();
//            return null;
//        }

        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
             FileInputStream fileInputStream = new FileInputStream(classFile)
        ) {

            byte[] buff = new byte[1024];
            int len;
            while ((len = fileInputStream.read(buff)) != -1) {
                baos.write(buff, 0, len);
            }
            baos.flush();
            return baos.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
}
